package my.springboot3.service.impl;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import my.springboot3.service.RedisService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public final class RedisServiceImpl implements RedisService {

    /**
     * 定义一个常量DURATION，表示键值对在Redis中的过期时长。
     * 这里设置为1小时（60分钟 * 60秒 * 1000毫秒）。
     */
    private final Long DURATION = 60 * 60 * 1000L;

    /**
     * 使用@Resource注解自动注入RedisTemplate对象。
     * RedisTemplate是Spring Data Redis提供的用于操作Redis的模板类。
     */
    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 声明一个ValueOperations类型的变量valueOperations，
     * 用于执行简单的键值对操作（如设置、获取和删除等）。
     */
    private ValueOperations<String, String> valueOperations;

    /**
     * 使用@PostConstruct注解标记的方法，在依赖注入完成后进行初始化操作。
     * 在这个方法中配置了RedisTemplate使用的序列化器，并初始化了valueOperations。
     */
    @PostConstruct
    public void init() {
        // 创建一个StringRedisSerializer实例，用于将字符串序列化为Redis可存储格式。
        RedisSerializer redisSerializer = new StringRedisSerializer();

        // 设置RedisTemplate的键序列化器为StringRedisSerializer。
        redisTemplate.setKeySerializer(redisSerializer);

        // 设置RedisTemplate的值序列化器为StringRedisSerializer。
        redisTemplate.setValueSerializer(redisSerializer);

        // 设置RedisTemplate的Hash结构的键序列化器为StringRedisSerializer。
        redisTemplate.setHashKeySerializer(redisSerializer);

        // 设置RedisTemplate的Hash结构的值序列化器为StringRedisSerializer。
        redisTemplate.setHashValueSerializer(redisSerializer);

        // 初始化valueOperations变量，以便后续可以直接使用opsForValue()方法进行操作。
        valueOperations = redisTemplate.opsForValue();
    }

    /**
     * 实现RedisService接口的set方法，用于向Redis中存入键值对，并设置过期时间。
     * @param key 键
     * @param value 值
     */
    @Override
    public void set(String key, String value) {
        // 使用valueOperations的set方法将键值对存入Redis，并设置过期时间为DURATION。
        valueOperations.set(key, value, DURATION, TimeUnit.MILLISECONDS);

        // 记录日志，输出存入Redis的键和值。
        log.info("key={}, value is: {} into redis cache", key, value);
    }

    /**
     * 实现RedisService接口的get方法，用于从Redis中获取指定键对应的值。
     * @param key 键
     * @return 返回Redis中存储的值
     */
    @Override
    public String get(String key) {
        // 使用valueOperations的get方法从Redis中获取指定键对应的值。
        String redisValue = valueOperations.get(key);

        // 记录日志，输出从Redis中获取到的值。
        log.info("get from redis, value is: {}", redisValue);

        // 返回获取到的值。
        return redisValue;
    }

    /**
     * 实现RedisService接口的delete方法，用于从Redis中删除指定键。
     * @param key 键
     * @return 返回删除操作是否成功
     */
    @Override
    public boolean delete(String key) {
        // 使用redisTemplate的delete方法从Redis中删除指定键。
        boolean result = redisTemplate.delete(key);

        // 记录日志，输出被删除的键。
        log.info("delete from redis, key is: {}", key);

        // 返回删除操作的结果。
        return result;
    }

    /**
     * 实现RedisService接口的getExpireTime方法，用于获取指定键的剩余有效时间。
     * @param key 键
     * @return 返回剩余有效时间（以秒为单位）
     */
    @Override
    public Long getExpireTime(String key) {
        // 使用valueOperations的getOperations方法获取RedisTemplate的操作对象，并调用getExpire方法获取剩余有效时间。
        return valueOperations.getOperations().getExpire(key);
    }
}